package chatserver;

import java.io.IOException;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

class ChatServer {

    private Set<Connection> set = new HashSet();
    public final static byte POST = 0x01;
    public final static byte ONLINE = 0x02;
    public final static byte ERROR = 0x03;      //???
    public final static byte RADIO = 0x04;
    public final static byte CAPTCHA = 0x05;
    public final static byte CLEAR = 0x07;
    public final static String DUMMY_CAPTCHA = "http://f.i.ua/ip0_c0_l0.png";
    public final static int TO_SAVE = 10;
    private boolean useCaptcha = true;
    private int chatPort = 1984;                // DEFAULT
    private int httpHandshake = 1985;           // DEFAULT
    private int online = 0;
    private int counter = 0;
    private ArrayBlockingQueue lastPosts = new ArrayBlockingQueue(TO_SAVE);
    public final static String HTML[] = {"[",
        "] <b>&lt;<a href=\"event:insert,",
        "\"><font color=\"#000000\">",
        "</font></a></b><b>&gt;</b> "
    };

    ChatServer() {
    }

    ChatServer(int chatPort, int httpHandshake) {
        this.chatPort = chatPort;
        this.httpHandshake = httpHandshake;
    }

    protected void removeUser(Connection c) {
        set.remove(c);
        if (c.isConnected()) {
            someoneLeaved();
        }
        System.out.println(c.getInetAddress() + ":" + c.getPort() + " disconnected");
    }

    public boolean usesCaptcha() {
        return useCaptcha;
    }

    protected synchronized void someoneEntered() {
        online++;
        sendOnline();
    }

    protected synchronized void someoneLeaved() {
        online--;
        sendOnline();
    }

    protected synchronized void sendMessage(String message, byte cmd) {
        Connection c;
        Iterator<Connection> iterator = set.iterator();


        switch (cmd) {
            case POST: {
                counter++;
                message = makePost(message, counter);
                savePost(message);
                System.out.println("POST: " + message);
                break;
            }
        }
        while (iterator.hasNext()) {
            try {
                c = iterator.next();
                c.sendMessage(message, cmd);
            } catch (Exception ex) {
                Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void savePost(String message) {
        if (lastPosts.size() == TO_SAVE) {
            lastPosts.poll();
        }
        lastPosts.add(message);
    }

    public String getLastPosts() {
        StringBuilder sb = new StringBuilder();
        Iterator iterator = lastPosts.iterator();

        while (iterator.hasNext()) {
            sb.append(iterator.next());
            sb.append("<br>");
        }
        return sb.toString();
    }

    private static String makePost(String message, int counter) {

        String sCounter = new Integer(counter).toString();
        StringBuilder sb = new StringBuilder();

        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();

        sb.append(HTML[0]);
        sb.append(dateFormat.format(date));
        sb.append(HTML[1]);
        sb.append(sCounter);
        sb.append(HTML[2]);
        sb.append(sCounter);
        sb.append(HTML[3]);
        sb.append(message);

        return sb.toString();
    }

    public void sendOnline() {
        sendMessage(Integer.toString(set.size()), ONLINE);
        //sendMessage(Integer.toString(online), ONLINE);
        System.out.println("online, set.size(): " + set.size());
    }

    private void startHHandhake() {
        Thread t = new Thread(new HttpHandshake(httpHandshake));
        t.setDaemon(true);
        t.start();
    }

    private void waitForConnection() {

        try {
            ServerSocket ssocket = new ServerSocket(chatPort, 0);
            System.out.println("Socket in ChatServer created");
            while (true) {
                Connection c = new Connection(ssocket.accept(), this);
                Thread thrSender = new Thread(c);
                thrSender.setDaemon(true);
                thrSender.start();
                set.add(c);
            }
        } catch (IOException ex) {
            Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void main(String args[]) {
        ChatServer cs = new ChatServer();
        cs.startHHandhake();
        cs.waitForConnection();
    }

    public static String getHash(byte[] b) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] thedigest = md.digest(b);
        BigInteger number = new BigInteger(1, thedigest);
        return number.toString(16);
    }
}